using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using BanZuiCloudControlAgent.Core.Mqtt;
using BanZuiCloudControlAgent.Core.Mqtt.Models;
using BanZuiCloudControlAgent.Core.Mqtt.Sender;
using BanZuiCloudControlAgent.Core.Tasks.Base;
using BanZuiCloudControlAgent.Core.Tasks.Enums;
using BanZuiCloudControlAgent.Core.Tasks.Models;
using BanZuiCloudControlAgent.Core.Tasks.Queue;
using BanZuiCloudControlAgent.Core.Tasks.Utils;
using BanZuiCloudControlAgent.Utils.Exceptions;
using BanZuiCloudControlAgent.Utils.Logging;

namespace BanZuiCloudControlAgent.Core.Tasks.Handlers
{
    /// <summary>
    /// 任务执行器，负责执行任务队列中的任务
    /// </summary>
    public class TaskExecutor
    {
        private readonly Logger _logger;
        private readonly string _deviceCode;
        private readonly TaskQueue _taskQueue;
        private readonly TaskDispatcher _taskDispatcher;
        private readonly TaskMutexManager _mutexManager;
        private MessageSenderMiddleware _messageSender;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="logger">日志记录器</param>
        /// <param name="deviceCode">设备编码</param>
        /// <param name="messageSender">消息发送中间件</param>
        public TaskExecutor(Logger logger, string deviceCode, MessageSenderMiddleware messageSender)
        {
            _logger = logger ?? throw new ArgumentNullException(nameof(logger));
            _deviceCode = deviceCode ?? throw new ArgumentNullException(nameof(deviceCode));
            _messageSender = messageSender ?? throw new ArgumentNullException(nameof(messageSender));
            _mutexManager = new TaskMutexManager();
            _taskQueue = new TaskQueue();
            _taskDispatcher = new TaskDispatcher(logger, _taskQueue, deviceCode, messageSender);
            
            // 订阅任务状态变更事件
            _taskQueue.TaskStatusChanged += TaskQueue_TaskStatusChanged;
            
            // 设置任务队列的执行委托，使用互斥管理器控制任务执行
            _taskQueue.SetExecuteTaskDelegate(ExecuteTaskWithMutexAsync);
        }
        
        /// <summary>
        /// 设置消息发送中间件
        /// </summary>
        /// <param name="messageSender">消息发送中间件</param>
        public void SetMessageSender(MessageSenderMiddleware messageSender)
        {
            _messageSender = messageSender ?? throw new ArgumentNullException(nameof(messageSender));
            _taskDispatcher.SetMessageSender(messageSender);
        }

        /// <summary>
        /// 启动任务执行器
        /// </summary>
        public void Start()
        {
            _logger.Info("启动任务执行器");
            _taskQueue.Start();
        }
        
        /// <summary>
        /// 停止任务执行器
        /// </summary>
        public void Stop()
        {
            _logger.Info("停止任务执行器");
            _taskQueue.Stop();
        }
        
        /// <summary>
        /// 获取任务队列
        /// </summary>
        /// <returns>任务队列</returns>
        public TaskQueue GetTaskQueue()
        {
            return _taskQueue;
        }

        /// <summary>
        /// 处理任务下发消息
        /// </summary>
        /// <param name="taskDispatch">任务下发消息</param>
        /// <returns>创建的任务</returns>
        public async Task<BaseTask> HandleTaskDispatchAsync(TaskDispatchModel taskDispatch)
        {
            try
            {
                return await _taskDispatcher.DispatchTaskAsync(taskDispatch);
            }
            catch (Exception ex)
            {
                // 使用TaskException包装异常
                var errorType = ex is ArgumentNullException ? TaskErrorType.InvalidParameters : TaskErrorType.ExecutionFailed;
                var taskId = taskDispatch?.GetPayload()?.TaskId;
                var message = $"处理任务下发消息失败: {ex.Message}";
                
                throw new TaskException(errorType, taskId, message, ex);
            }
        }
        
        /// <summary>
        /// 处理更新任务消息
        /// </summary>
        /// <param name="updateTask">更新任务消息</param>
        /// <returns>创建的任务</returns>
        public async Task<BaseTask> HandleUpdateTaskAsync(UpdateTaskModel updateTask)
        {
            try
            {
                return await _taskDispatcher.DispatchUpdateTaskAsync(updateTask);
            }
            catch (Exception ex)
            {
                // 使用TaskException包装异常
                var errorType = ex is ArgumentNullException ? TaskErrorType.InvalidParameters : TaskErrorType.ExecutionFailed;
                var message = $"处理更新任务消息失败: {ex.Message}";
                
                throw new TaskException(errorType, message, ex);
            }
        }
        
        /// <summary>
        /// 处理配置消息
        /// </summary>
        /// <param name="configModel">配置消息</param>
        /// <returns>创建的任务</returns>
        public async Task<BaseTask> HandleConfigAsync(ConfigModel configModel)
        {
            try
            {
                return await _taskDispatcher.DispatchConfigTaskAsync(configModel);
            }
            catch (Exception ex)
            {
                // 使用TaskException包装异常
                var errorType = ex is ArgumentNullException ? TaskErrorType.InvalidParameters : TaskErrorType.ExecutionFailed;
                var message = $"处理配置消息失败: {ex.Message}";
                
                throw new TaskException(errorType, message, ex);
            }
        }
        
        /// <summary>
        /// 使用互斥管理器执行任务
        /// </summary>
        /// <param name="task">要执行的任务</param>
        /// <param name="context">任务上下文</param>
        /// <returns>任务执行结果</returns>
        private async Task<TaskResult> ExecuteTaskWithMutexAsync(ITask task, TaskContext context)
        {
            // 获取任务所属的任务组
            TaskGroup taskGroup = TaskGroupHelper.GetTaskGroup(task.TaskType);
            _logger.Debug($"任务 {task.TaskId} 属于任务组 {taskGroup}");
            
            try
            {
                // 尝试获取任务组的执行锁
                // 如果无法获取锁，则任务将保持在队列中等待
                bool lockAcquired = await _mutexManager.TryAcquireGroupLockAsync(taskGroup);
                
                if (!lockAcquired)
                {
                    _logger.Warn($"无法获取任务组 {taskGroup} 的执行锁，任务 {task.TaskId} 将稍后重试");
                    return TaskResult.Retry($"任务组 {taskGroup} 已被占用，稍后重试");
                }
                
                try
                {
                    // 执行任务
                    _logger.Info($"开始执行任务 {task.TaskId}，任务组 {taskGroup}");
                    return await task.ExecuteAsync(context);
                }
                finally
                {
                    // 释放任务组的执行锁
                    _mutexManager.ReleaseGroupLock(taskGroup);
                    _logger.Debug($"释放任务组 {taskGroup} 的执行锁，任务 {task.TaskId} 执行完成");
                }
            }
            catch (Exception ex)
            {
                _logger.Error($"执行任务 {task.TaskId} 时发生异常: {ex.Message}", ex);
                return TaskResult.Failure($"执行任务时发生异常: {ex.Message}", ex);
            }
        }
        
        /// <summary>
        /// 任务队列状态变更事件处理
        /// </summary>
        /// <param name="sender">事件源</param>
        /// <param name="e">事件参数</param>
        private void TaskQueue_TaskStatusChanged(object sender, TaskStatusChangedEventArgs e)
        {
            try
            {
                _logger.Debug($"任务状态变更: {e.Task.TaskId}, 状态: {e.Task.Status}, 进度: {e.Task.Progress}");
                
                // 使用消息发送中间件发送任务状态上报消息
                // 无需关心MQTT连接状态，中间件会处理消息缓存
                Task<bool> sendTask;
                
                // 根据任务状态选择合适的上报方法
                switch (e.Task.Status)
                {
                    case TaskState.Running:
                        sendTask = _messageSender.SendTaskProgressReportAsync(
                            e.Task.TaskId,
                            e.Task.TaskType.ToString(),
                            e.Task.Progress,
                            e.Task.Result?.Message,
                            ConvertToDataDictionary(e.Task.Result?.Data)
                        );
                        break;
                    case TaskState.Completed:
                        sendTask = _messageSender.SendTaskSuccessReportAsync(
                            e.Task.TaskId,
                            e.Task.TaskType.ToString(),
                            e.Task.Result?.Message,
                            ConvertToDataDictionary(e.Task.Result?.Data)
                        );
                        break;
                    case TaskState.Failed:
                        sendTask = _messageSender.SendTaskFailedReportAsync(
                            e.Task.TaskId,
                            e.Task.TaskType.ToString(),
                            e.Task.ErrorMessage ?? e.Task.Result?.Message ?? "任务失败",
                            ConvertToDataDictionary(e.Task.Result?.Data)
                        );
                        break;
                    case TaskState.Paused:
                        sendTask = _messageSender.SendTaskPauseReportAsync(
                            e.Task.TaskId,
                            e.Task.TaskType.ToString()
                        );
                        break;
                    case TaskState.Pending:
                        sendTask = _messageSender.SendTaskStartReportAsync(
                            e.Task.TaskId,
                            e.Task.TaskType.ToString()
                        );
                        break;
                    default:
                        // 默认使用通用上报方法
                        sendTask = _messageSender.SendTaskReportAsync(
                            e.Task.TaskId,
                            e.Task.TaskType.ToString(),
                            (int)e.Task.Status,
                            e.Task.Progress,
                            e.Task.Result,
                            e.Task.ErrorMessage
                        );
                        break;
                }
                
                // 处理发送结果
                sendTask.ContinueWith(t =>
                {
                    if (t.Exception != null)
                    {
                        _logger.Error($"发送任务状态上报消息失败: {t.Exception.InnerException?.Message}", t.Exception.InnerException);
                    }
                });
            }
            catch (Exception ex)
            {
                _logger.Error($"处理任务状态变更事件失败: {ex.Message}", ex);
            }
        }
        
        /// <summary>
        /// 将对象转换为Dictionary<string, object>
        /// </summary>
        /// <param name="data">要转换的数据</param>
        /// <returns>转换后的字典</returns>
        private Dictionary<string, object> ConvertToDataDictionary(object data)
        {
            if (data == null)
            {
                return null;
            }
            
            // 如果已经是Dictionary<string, object>类型，直接返回
            if (data is Dictionary<string, object> dictData)
            {
                return dictData;
            }
            
            // 否则创建一个新的Dictionary并添加数据
            return new Dictionary<string, object> { { "data", data } };
        }
    }
} 